#pragma once

#include <signal.h>
#include <unistd.h>
#include <stdlib.h> 
#include <sys/types.h>
#include <fcntl.h>

const char* root = "/";
const char* dev_null = "/dev/null";

bool Daemon(bool nochdir, bool noclose)
{
    // 1、忽略可能引起程序异常退出的信号 SIGCHLD SIGPIPE
    signal(SIGCHLD,SIG_IGN);
    signal(SIGPIPE,SIG_IGN);
    // 2、创建子进程，让父进程退出，使得子进程不成为组长
    pid_t pid = fork();
    if(pid > 0) exit(0);
    // 3、设置自己成为一个新的会画，setsid
    setsid();
    // 4、每一个进程都有自己的CWD（当前工作路径），是否将当前进程的CWD改为根目录
    // ​	改为根目录以后，进程可以以绝对路径的方式找到操作系统中的文件
    if(nochdir)
        chdir(root);

    // 5、变成守护进程以后，就不需要与用户的输入、输出和错误进行关联了
    // ​	可以将它们全部关闭，但难免服务器中会有输入、输出和错误
    // ​	向关闭的文件描述符中写入可能会导致进程退出
    // ​	所以这里将它们关闭不是最优解，而是将它们重定向到/dev/null中
    // ​	因为写入到/dev/null的数据会被直接丢弃，而从/dev/null读取信息，会默认读取到文件结尾
    if(noclose)
    {
        int fd = open(dev_null,O_RDWR);
        if(fd > 0)
        {
            dup2(fd,0);
            dup2(fd,1);
            dup2(fd,2);
            close(fd);
        }
    }
    else  // 不推荐
    {
        close(0);
        close(1);
        close(2);
    }

    return true;
}